/*
 * @Descripttion: 
 * @version: 
 * @Author: wangzhilei
 * @Date: 2021-10-06 00:14:43
 * @LastEditors: wangzhilei
 * @LastEditTime: 2021-10-06 05:39:15
 */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>  
#include <sys/wait.h>

int count;  //current copy number
int file_size; //the file size
void sig_alarm(int arg);
void sig_usr(int sig);

int main(int argc,char *argv[])
{
    pid_t pid;
    int i;
    int fd_src,fd_des;
    char buf[128];
    //判断命令行输入参数
    if(argc!=3)
    {
        printf("check the format:comm src_file des_file\n");
        return -1;
    }
    //打开copy file
    if ((fd_src=open(argv[1],O_RDONLY))==-1)
    {
        perror("open file src");
        exit(EXIT_FAILURE);
    }
    //获取复制文件大小
    file_size=lseek(fd_src,0,SEEK_END);
    lseek(fd_src,0,SEEK_SET);

    //打开目标文件
    if((fd_des=open(argv[2],O_RDWR|O_CREAT,0644))==-1)
    {
        perror("open file fd_fdes");
        exit(EXIT_FAILURE);
    }
    //创建子进程
    if((pid=fork())==-1){
        perror("fork err");
        exit(EXIT_FAILURE);
    }else if (pid>0)//父进程,读取拷贝文件到目标文件，并统计写入字节数
    {
        signal(SIGUSR1,sig_usr);
        do{
            bzero(buf,128);
            //读取拷贝文件到缓冲区
            if((i=read(fd_src,buf,1))==-1)
            {
                perror("read");
                exit(EXIT_FAILURE);
            }
            else if (i==0)
            {
                kill(pid,SIGINT);//通知子进程退出
                break;
            }
            else{
                //写入目标文件
                if(write(fd_des,buf,i)==-1){
                    perror("write");
                    exit(EXIT_FAILURE);
                }
                count+=i;//统计写入的字节数
                usleep(1);
            }
            
        }while (i!=0);
        //阻塞等待
        wait(NULL);
        exit(EXIT_SUCCESS);
    }
    else if (pid==0)//子进程
    {
        signal(SIGALRM,sig_alarm);
        ualarm(1,1);
        while (1)
        {
            ;
        }
        exit(EXIT_SUCCESS);
    }
}
void sig_alarm(int arg)
{
    kill(getppid(),SIGUSR1);
}
void sig_usr(int sig)
{
    float i;
    i=(float)count/(float)file_size;
    printf("curent over :%0.0f%%\n",i*100);
}